(function () {
  /**
   * 支持识别的快捷键类型：若干任意修饰键 + 任意一个非修饰键
   */
  class ShortcutBinder {

    modifierKeysMap = {
      'SHIFT': 'Shift',
      'META': 'Meta',
      'CONTROL': 'Control',
      'ALT': 'Alt'
    };

    constructor() {
      this.shortcuts = [];

      this.init();
    }

    init() {
      document.addEventListener('keydown', (e) => {

        const targetShortcut = this._getTargetShortcut(e);

        if (!targetShortcut.length) return;

        targetShortcut.forEach(({ callback }) => {
          callback();
        });
      });
    }

    _getModifiers(e) {
      let modifiers = [];

      if (e.ctrlKey) modifiers.push(this.modifierKeysMap['CONTROL']);
      if (e.altKey) modifiers.push(this.modifierKeysMap['ALT']);
      if (e.shiftKey) modifiers.push(this.modifierKeysMap['SHIFT']);
      if (e.metaKey) modifiers.push(this.modifierKeysMap['META']); // Mac上Command键

      return modifiers;
    }

    _getTargetShortcut(e) {
      const modifiers = this._getModifiers(e);
      const key = e.key;

      const targets = [];

      this.shortcuts.forEach((shortcut) => {
        const { shortcut: shortcutStr, callback } = shortcut;
        const [nonModifierKey, ...modifierKeys] = shortcutStr.split('+').reverse();

        const isHit = this._isArraySame(modifiers, modifierKeys) && key === nonModifierKey;

        if (!isHit) return;
        targets.push(shortcut);
      })

      return targets;
    }

    _isArraySame(a, b) {

      const setA = new Set(a);
      const setB = new Set(b);

      if (setA.size !== setB.size) return false;

      for (const item of setA) {
        if (!setB.has(item)) return false;
      }

      return true;
    }

    /**
     *  非修饰键的需要在最后
     */
    bind(shortcut, callback) {
      this.shortcuts.push({
        shortcut,
        callback
      });
    }

  }

  window['shortcutBinder'] = new ShortcutBinder();
})();